package com.ship.contract.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ship.common.core.enums.MessageTypeEnum;
import com.ship.common.core.enums.ModuleUrlEnum;
import com.ship.common.core.exception.BusException;
import com.ship.common.core.utils.BeanCopyUtils;
import com.ship.common.core.utils.StringUtils;
import com.ship.common.core.web.domain.BaseResultCode;
import com.ship.common.security.utils.SecurityUtils;
import com.ship.contract.bean.*;
import com.ship.contract.bean.vo.ConResourceMemorandumVo;
import com.ship.contract.bean.vo.PortNameVo;
import com.ship.contract.bean.vo.QueryTimeZoneSwitchingInfo;
import com.ship.contract.mapper.ConResourceMemorandumMapper;
import com.ship.contract.mapper.SpPortInformationMapper;
import com.ship.contract.service.*;
import com.ship.contract.utils.FileUtil;
import com.ship.contract.mapper.ConstantMapper;
import com.ship.contract.utils.ObjectUtils;
import com.ship.system.api.BpmInstanceService;
import com.ship.system.api.RemoteDispatchService;
import com.ship.system.api.RemoteMessageSendService;
import com.ship.system.api.RemoteUserService;
import com.ship.system.api.domain.SysMessageSend;
import com.ship.system.api.domain.dispatch.ShipInfoUpdateDto;
import com.ship.system.api.model.ProcessInstanceParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author tangshixuan
 * @date 2023-8-31
 */
@Service("ConResourceMemorandumService")
public class ConResourceMemorandumServiceImpl extends ContractBaseServiceImpl<ConResourceMemorandumMapper, ConResourceMemorandum> implements ConResourceMemorandumService {
    @Autowired
    private ConOperateService conOperateService;

    @Autowired
    private ConAllLabelService conAllLabelService;

    @Autowired
    private ConFilesService conFilesService;

    @Autowired
    private ConExcellentCasesService conExcellentCasesService;

    @Autowired
    private ConResourceMemorandumPositionService conResourceMemorandumPositionService;

    @Autowired
    private ConResourceMainService conResourceMainService;

    @Autowired
    private ConstantMapper constantMapper;

    @Autowired
    private ConResourceMemorandumMapper conResourceMemorandumMapper;

    @Autowired
    private ConResourceFullNameService conResourceFullNameService;

    @Resource
    BpmInstanceService bpmInstanceService;

    @Resource
    private RemoteUserService remoteUserService;

    @Resource
    private RemoteMessageSendService remoteMessageSendService;

    @Resource
    private RemoteDispatchService remoteDispatchService;

    @Value("${file.http-domain}")
    private String httpUrl;
    @Value("${file.https-domain}")
    private String httpsUrl;

    @Autowired
    private SpPortInformationMapper portInformationMapper;

    @Override
    public void delApply(Long id) {
        ConResourceMemorandum conResourceMemorandum = super.getById(id);
        if (conResourceMemorandum == null) {
            throw new BusException("删除申请失败!,该合同不存在", BaseResultCode.GENERAL_ERROR);
        }
        if (conResourceMemorandum.getDelApply() == 1) {
            throw new BusException("当前合同已发起删除申请，请勿重复提交", BaseResultCode.GENERAL_ERROR);
        }
        conResourceMemorandum.setDelApply(1);
        //启动删除审批流程
        ProcessInstanceParam param = new ProcessInstanceParam();
        param.setBussinessId(id);
        param.setBpmKey(BpmInstanceService.SYSTEM_DELETE_BPM_KEY);
        Map<String, Object> map = new HashMap<>();
        map.put("serviceType", 8);
        map.put("module", "con");
        map.put("moduleName", "资源合同");
        map.put("reason", "");
        param.setParams(map);
        String processInstanceId = bpmInstanceService.startProcessInstance(param);
        conResourceMemorandum.setDeleteProcessInstanceId(processInstanceId);
        super.updateById(conResourceMemorandum);
    }

    @Override
    public Map<String, Object> detail(Long id) {
        Map<String, Object> result = new HashMap<>();
        ConResourceMemorandum conRe = super.getById(id);
        result.put("data", conRe);
        result.put("optRecord", conOperateService.listByConId(id));
        result.put("contractLabels", conAllLabelService.listByConId(id));
        List<ConFiles> conFiles = conFilesService.listByConId(id);
        if (conFiles != null && conFiles.size() > 0) {
            conFiles.stream().forEach(c -> {
                c.setUrl(c.getUrl().replace(httpUrl, httpsUrl));
                c.setNewUrl(c.getUrl());
            });
        }
        result.put("files", conFiles);
        return result;
    }

    @Override
    public QueryTimeZoneSwitchingInfo queryTimezoneById(Long id, String type) throws ParseException {
        QueryTimeZoneSwitchingInfo queryTimeZoneSwitchingInfo = new QueryTimeZoneSwitchingInfo();
        ConResourceMemorandum conRe = super.getById(id);
        if (null != conRe){
            if (conRe.getTradeModel() == 1){
                if (StringUtils.isNotEmpty(conRe.getLoadingPort()) && !"No restriction".equals(conRe.getLoadingPort())){
                    QueryTimeZoneSwitchingInfo info = this.timeZoneSwitching(conRe.getLoadingPort(), DateUtil.format(conRe.getDeliveryWindowBegin(), DatePattern.NORM_DATETIME_MINUTE_FORMATTER), DateUtil.format(conRe.getDeliveryWindowEnd(), DatePattern.NORM_DATETIME_MINUTE_FORMATTER));
                    return info;
                }else {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                    Date startDate = dateFormat.parse(DateUtil.format(conRe.getDeliveryWindowBegin(), DatePattern.NORM_DATETIME_MINUTE_FORMATTER));
                    Date endDate = dateFormat.parse(DateUtil.format(conRe.getDeliveryWindowEnd(), DatePattern.NORM_DATETIME_MINUTE_FORMATTER));
                    queryTimeZoneSwitchingInfo.setNowTime(dateFormat.format(startDate)+" - "+dateFormat.format(endDate));
                    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
                    queryTimeZoneSwitchingInfo.setUtcTime(dateFormat.format(startDate)+" - "+dateFormat.format(endDate));
                }
            }else if (conRe.getTradeModel() == 2 || conRe.getTradeModel() == 3){
                if (StringUtils.isNotEmpty(conRe.getUnloadingPort()) && !"No restriction".equals(conRe.getUnloadingPort())){
                    QueryTimeZoneSwitchingInfo info = this.timeZoneSwitching(conRe.getUnloadingPort(), DateUtil.format(conRe.getDeliveryWindowBegin(), DatePattern.NORM_DATETIME_MINUTE_FORMATTER), DateUtil.format(conRe.getDeliveryWindowEnd(), DatePattern.NORM_DATETIME_MINUTE_FORMATTER));
                    return info;
                }else {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                    Date startDate = dateFormat.parse(DateUtil.format(conRe.getDeliveryWindowBegin(), DatePattern.NORM_DATETIME_MINUTE_FORMATTER));
                    Date endDate = dateFormat.parse(DateUtil.format(conRe.getDeliveryWindowEnd(), DatePattern.NORM_DATETIME_MINUTE_FORMATTER));
                    queryTimeZoneSwitchingInfo.setNowTime(dateFormat.format(startDate)+" - "+dateFormat.format(endDate));
                    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
                    queryTimeZoneSwitchingInfo.setUtcTime(dateFormat.format(startDate)+" - "+dateFormat.format(endDate));
                }
            }
        }
        return queryTimeZoneSwitchingInfo;
    }

    public QueryTimeZoneSwitchingInfo timeZoneSwitching(String portName,String startCalculationTime,String endCalculationTime) throws ParseException {
        QueryTimeZoneSwitchingInfo info = new QueryTimeZoneSwitchingInfo();
        String timeZoneName = baseMapper.queryTimeZoneByPortName(portName);
        if (StringUtils.isEmpty(timeZoneName)){
            timeZoneName = baseMapper.queryTimeZoneByTerminalName(portName);
        }
        if (StringUtils.isNotEmpty(timeZoneName)) {
            TimeZone timeZone = TimeZone.getTimeZone(timeZoneName);
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            dateFormat.setTimeZone(timeZone);
            try {
                Date startDate = dateFormat.parse(startCalculationTime);
                Date endDate = dateFormat.parse(endCalculationTime);
                info.setLocalTime(dateFormat.format(startDate) + " - " + dateFormat.format(endDate));
                dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
                info.setUtcTime(dateFormat.format(startDate) + " - " + dateFormat.format(endDate));
                TimeZone otherTimeZone = TimeZone.getTimeZone("GMT+8");
                dateFormat.setTimeZone(otherTimeZone);
                info.setNowTime(dateFormat.format(startDate) + " - " + dateFormat.format(endDate));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return info;
    }

    @Transactional
    @Override
    public void excellent(ConExcellentCases conExcellentCases, String currentUserName) {
        ConResourceMemorandum conResourceMemorandum = super.getById(conExcellentCases.getId());
        if (conResourceMemorandum == null) {
            throw new BusException("申请失败!,该合同不存在", BaseResultCode.GENERAL_ERROR);
        }
        ConExcellentCases existByConId = conExcellentCasesService.getAllByConId(conExcellentCases.getId());
        if (existByConId != null) {
            throw new BusException("该合同已经存在优秀案例", BaseResultCode.GENERAL_ERROR);
        }

        conExcellentCases.setId(null);
        conExcellentCases.setContractName(conResourceMemorandum.getContractName());
        conExcellentCases.setContractNumber(conResourceMemorandum.getContractNumber());
        conExcellentCases.setConId(conResourceMemorandum.getId());
        conExcellentCases.setTypeOfContract(8);
        conExcellentCases.setApplicant(SecurityUtils.getUsername());
        conExcellentCases.setCreateBy(SecurityUtils.getUsername());
        //启动审批流程
        ProcessInstanceParam param = new ProcessInstanceParam();
        param.setBussinessId(conResourceMemorandum.getId());
        param.setBpmKey(BpmInstanceService.CON_RESOURCE_BOM_KEY);
        Map<String, Object> map = new HashMap<>();
        try {
            map = ObjectUtils.objectToMap(conExcellentCases);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        map.put("moduleName", "资源合同");
        map.put("reason", conExcellentCases.getExcellent());
        map.put("serviceType", 8);
        param.setParams(map);
        String processInstanceId = bpmInstanceService.startProcessInstance(param);
        conExcellentCases.setProcessInstanceId(processInstanceId);
        conExcellentCasesService.save(conExcellentCases);
        conResourceMemorandum.setExcellent(1);
        super.updateById(conResourceMemorandum);
    }

    @Override
    public void saveCon(ConResourceMemorandum conResourceMemorandum) {
        // 设置合同状态默认值为 已签订
        conResourceMemorandum.setStatus(1);
        conResourceMemorandum.setDelApply(0);

        conResourceMemorandum.setContractName(editContractName(conResourceMemorandum));
        conResourceMemorandum.setContractNumber(editContractNumbers(conResourceMemorandum));
        conResourceMemorandum.setCurrency(1);
        ConResourceMain main = conResourceMainService.getById(conResourceMemorandum.getMainContract());
        if (main != null) {
            conResourceMemorandum.setMainContractName(main.getContractName());
        }
//        conResourceMemorandum.setDemurrageRate(conResourceMemorandum.getDemurrageRateVal());
//        conResourceMemorandum.setEvaporationRate(conResourceMemorandum.getEvaporationRateVal());

        super.save(conResourceMemorandum);
        ConFiles conFile = new ConFiles();
        conFile.setConId(conResourceMemorandum.getId());
        conFile.setFileType(1);
        String url = conResourceMemorandum.getFilePath();
        String path = url.replace(httpUrl, httpsUrl);
        conFile.setUrl(path);
        conFile.setNewUrl(path);
        conFile.setFileName(path.substring(path.lastIndexOf("/") + 1, path.length()));
        conFile.setScanPdf(FileUtil.getIsScanPdf(path));

        Long conId = conResourceMemorandum.getId();
        conResourceMemorandumMapper.updateConId(path, conId);
        //保存附件
        conFilesService.save(conFile);
        conOperateService.saveByCon("新增合同", conResourceMemorandum.getId());

        //触发消息通知
        SysMessageSend messageSend = new SysMessageSend();
        messageSend.setMessageUrl(ModuleUrlEnum.ZYHTBWLXQ.getUrl() + conResourceMemorandum.getId());
        messageSend.setMessageType(MessageTypeEnum.MESSAGE_TYPE_1.getCode());
        messageSend.setContentParam(new String[]{"资源合同备忘录"});
        remoteMessageSendService.messageSend(messageSend);

        if(conResourceMemorandum.getResourceFullName() !=null){
            List<ConResourceFullName> conIdByUser = conResourceFullNameService.getConIdByUser(SecurityUtils.getUsername(),conResourceMemorandum.getResourceFullName());
            if(conIdByUser == null || conIdByUser.isEmpty()){
                saveResourceFullName(conResourceMemorandum);
            }
        }
    }

    @Override
    public void updateCon(ConResourceMemorandum conResourceMemorandum) {
//        ConResourceMemorandum OldConResourceMemorandu = conResourceMemorandumMapper.getById(conResourceMemorandum.getId());
        ConResourceMemorandum oldConResourceMemorandum = conResourceMemorandumMapper.getById(conResourceMemorandum.getId());

        conResourceMemorandum.setContractNumber(oldConResourceMemorandum.getContractNumber());

        //原合同编号尾号+1，方便比较
        //编辑后累加合同编号//
        //String oldContractNumber = incrementLastDigit(oldConResourceMemorandum.getContractNumber());
        //编辑后累加合同编号//
        conResourceMemorandum.setContractName(editContractName(conResourceMemorandum));
        //编辑后累加合同编号//
//        String newContractNumbers = editContractNumbers(conResourceMemorandum);
//        if (newContractNumbers.equals(oldContractNumber)){
//            conResourceMemorandum.setContractNumber(oldConResourceMemorandum.getContractNumber());
//        }else {
//            conResourceMemorandum.setContractNumber(newContractNumbers);
//        }
        //编辑后累加合同编号//
        String newMainContractName = conResourceMainService.getNameById(conResourceMemorandum.getMainContract());
        if (oldConResourceMemorandum.getMainContract() == null) {
            conResourceMemorandum.setMainContractName(newMainContractName);
        } else {
            if ((oldConResourceMemorandum.getMainContract()).equals(conResourceMemorandum.getMainContract())) {
                conResourceMemorandum.setMainContractName(oldConResourceMemorandum.getMainContractName());
            } else {
                conResourceMemorandum.setMainContractName(newMainContractName);
            }
        }

        super.updateById(conResourceMemorandum);

        //更新船舶关联的其他信息
//        ShipInfoUpdateDto updateShipInfo = new ShipInfoUpdateDto();
//        updateShipInfo.setId(conResourceMemorandum.getId());
//        updateShipInfo.setContractName(conResourceMemorandum.getContractName());
//        updateShipInfo.setTradeModel(conResourceMemorandum.getTradeModel());
//        updateShipInfo.setTradeBody(conResourceMemorandum.getTradeBody());
//        updateShipInfo.setTradeType(conResourceMemorandum.getTradeType());
//        updateShipInfo.setBuyer(conResourceMemorandum.getBuyer());
//        updateShipInfo.setSeller(conResourceMemorandum.getSeller());
//        remoteDispatchService.updateDispatchInfo(updateShipInfo);

        ConExcellentCases conExcellentCases = conExcellentCasesService.getAllByConId(conResourceMemorandum.getId());
        if (conExcellentCases != null) {
            conExcellentCases.setContractName(conResourceMemorandum.getContractName());
            conExcellentCases.setContractNumber(conResourceMemorandum.getContractNumber());
            conExcellentCasesService.updateById(conExcellentCases);
        }
        conOperateService.saveByCon("修改合同", conResourceMemorandum.getId());

        //触发消息通知
        SysMessageSend messageSend = new SysMessageSend();
        messageSend.setMessageUrl(ModuleUrlEnum.ZYHTBWLXQ.getUrl() + conResourceMemorandum.getId());
        messageSend.setMessageType(MessageTypeEnum.MESSAGE_TYPE_2.getCode());
        messageSend.setContentParam(new String[]{conResourceMemorandum.getContractName(), conResourceMemorandum.getContractNumber()});
        remoteMessageSendService.messageSend(messageSend);

        if(conResourceMemorandum.getResourceFullName() !=null){
            List<ConResourceFullName> conIdByUser = conResourceFullNameService.getConIdByUser(SecurityUtils.getUsername(),conResourceMemorandum.getResourceFullName());
            if(conIdByUser == null || conIdByUser.isEmpty()){
                saveResourceFullName(conResourceMemorandum);
            }
        }
    }

    //根据信息拼接合同名字
    @Override
    public String editContractName(ConResourceMemorandum conResourceMemorandum) {
        // 获取合同名字拼接字段
        String str1 = constantMapper.findConstLabel("贸易主体", String.valueOf(conResourceMemorandum.getTradeBody()));
        String str2 = constantMapper.findConstLabel("交货方式", String.valueOf(conResourceMemorandum.getDeliveryType()));
        String str3 = constantMapper.findConstLabel("贸易模式", String.valueOf(conResourceMemorandum.getTradeModel()));
        String str4 = null;
        if (str3.equals("采购")) {
            str4 = conResourceMemorandum.getSeller();
        } else if (str3.equals("销售")) {
            str4 = conResourceMemorandum.getBuyer();
        } else if (str3.equals("返装销售")) {
            str4 = conResourceMemorandum.getBuyer();
        }
        Date signingDate = conResourceMemorandum.getSigningDate();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
        String str5 = sdf.format(signingDate);
        String contractName = "CN-" + str1 + "-" + str2 + str3 + "-" + str4 + "-" + str5;
        return contractName;
    }

    //根据信息拼接合同编号
    @Override
    public String editContractNumbers(ConResourceMemorandum conResourceMemorandum) {
        // 获取所有合同编号
        List<String> strings = conResourceMemorandumMapper.getAllContractNumbers();
        String ContractNum = null;
        if (conResourceMemorandum.getDeliveryType() == 1) {
            if (conResourceMemorandum.getTradeModel() == 1) {
                int maxNumber = extractAndFindMaxNumber(strings, "FOB-B");
                ContractNum = "CN-FOB-B-" + maxNumber;
            } else if (conResourceMemorandum.getTradeModel() == 2) {
                int maxNumber = extractAndFindMaxNumber(strings, "FOB-S");
                ContractNum = "CN-FOB-S-" + maxNumber;
            } else if (conResourceMemorandum.getTradeModel() == 3) {
                int maxNumber = extractAndFindMaxNumber(strings, "FOB-R");
                ContractNum = "CN-FOB-R-" + maxNumber;
            }
        } else if (conResourceMemorandum.getDeliveryType() == 2) {
            if (conResourceMemorandum.getTradeModel() == 1) {
                int maxNumber = extractAndFindMaxNumber(strings, "DES-B");
                ContractNum = "CN-DES-B-" + maxNumber;
            } else if (conResourceMemorandum.getTradeModel() == 2) {
                int maxNumber = extractAndFindMaxNumber(strings, "DES-S");
                ContractNum = "CN-DES-S-" + maxNumber;
            } else if (conResourceMemorandum.getTradeModel() == 3) {
                int maxNumber = extractAndFindMaxNumber(strings, "DES-R");
                ContractNum = "CN-DES-R-" + maxNumber;
            }
        }
        return ContractNum;
    }

    @Override
    public List<ConResourceMemorandumVo> selectAllContractNumbers(ConResourceMemorandumSelect dto) {
        List<ConResourceMemorandumVo> resultData = new LinkedList<>();
        List<ConResourceMemorandum> resourceMemorandums = this.baseMapper.selectList(
                new LambdaQueryWrapper<ConResourceMemorandum>()
                        .in(dto.getTradeModels().size() > 0, ConResourceMemorandum::getTradeModel, dto.getTradeModels())
                        .in(dto.getTradeTypes().size() > 0, ConResourceMemorandum::getTradeType, dto.getTradeTypes())
        );
        Boolean checkContract = dto.getUseType() != null && dto.getUseType().intValue() == 1 ? true : false;
        for (ConResourceMemorandum resourceMemorandum : resourceMemorandums) {
            if(checkContract){
                Integer count = this.baseMapper.getDispatchUseCountByContractId(resourceMemorandum.getId());
                if(count > 0){
                    continue;
                }
            }
            ConResourceMemorandumVo resultVo = new ConResourceMemorandumVo();
            BeanCopyUtils.copy(resourceMemorandum, resultVo);
            resultData.add(resultVo);
//            resourceMemorandum.setDeliveryWindowBegin(
//                    DateUtil.parse(resourceMemorandum.getDeliveryWindowBegin().toString(),"yyyy-MM-dd HH:mm:ss"));
        }
        return resultData;
    }

    /**
     * 获取宝船网港口名称
     *
     * @return
     */
    @Override
    public List<PortNameVo> getPortNames(String name) {
        List<PortNameVo> portNameVos = new ArrayList<>();
        portNameVos.add(new PortNameVo("No restriction","No restriction"));
        Map<String, List<SpPortInformation>> portInforMap = portInformationMapper.selectList(new LambdaQueryWrapper<>()).stream().collect(Collectors.groupingBy(SpPortInformation::getPortNameEnglish));
        for (String portName : portInforMap.keySet()) {
            List<SpPortInformation> portInformations = portInforMap.get(portName);
            if (null != portInformations && portInformations.size() > 0) {
                if (portInformations.size() > 1) {
                    List<PortNameVo> finalPortNameVos = new ArrayList<>();
                    portInformations.stream().forEach(p->{
                        PortNameVo portNameVo = new PortNameVo();
                        if(p.getPortType().equals("1")){
                            portNameVo.setLabel(p.getPortNameEnglish()+" 港口");
                            portNameVo.setValue(p.getId().toString());
                        }else if(p.getPortType().equals("2")){
                            portNameVo.setLabel(p.getPortNameEnglish()+" 接收站");
                            portNameVo.setValue(p.getId().toString());
                        }
                        finalPortNameVos.add(portNameVo);
                    });
                    portNameVos.addAll(finalPortNameVos);
                } else {
                    PortNameVo portNameVo = new PortNameVo();
                    SpPortInformation portInformation = portInformations.get(0);
                    if(null != portInformation){
                        portNameVo.setLabel(portInformation.getPortNameEnglish());
                        portNameVo.setValue(portInformation.getId().toString());
                        portNameVos.add(portNameVo);
                    }
                }
            }
        }

        if(StringUtils.isNotBlank(name)){
            portNameVos = portNameVos.stream().filter(p->p.getLabel().toUpperCase().contains(name.toUpperCase())).collect(Collectors.toList());
        }

        return portNameVos;
    }

    /**
     * 保存新的资源方全称
     * @param conResourceMemorandum
     */
    public void saveResourceFullName(ConResourceMemorandum conResourceMemorandum) {
        ConResourceFullName conResourceFullName = new ConResourceFullName();
        conResourceFullName.setConId(conResourceMemorandum.getId());
        conResourceFullName.setResourceFullName(conResourceMemorandum.getResourceFullName());
        conResourceFullNameService.setResourceFullName(conResourceFullName);
    }
}
